package com.tanhan.mindapp.config.inter;

import com.tanhan.mindapp.utils.TokenUtils;
import io.jsonwebtoken.Claims;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

@Component
@Slf4j
public class JwtAuthenticationFilter extends OncePerRequestFilter {
    @Autowired
    private TokenUtils tokenUtils;

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response,
                                    FilterChain filterChain) throws ServletException, IOException {

        // 获取Authorization头
        String authorization = request.getHeader("Authorization");

        // 对于公开路径，即使token无效也应该放行而不是返回401
        String requestURI = request.getRequestURI();
        if (isPublicPath(requestURI) || authorization == null) {
            SecurityContextHolder.clearContext();
            filterChain.doFilter(request, response);
            return;
        }

        try {
            // 解析token
            Claims claims = tokenUtils.parseJwt(authorization);

            // 将claims信息存入request属性中，供后续使用
            request.setAttribute("claims", claims);

            // 从token中直接获取用户权限信息
            List<SimpleGrantedAuthority> authorities = new ArrayList<>();
            if (claims.get("authorities") != null) {
                List<String> permissions = (List<String>) claims.get("authorities");
                // 过滤掉null值和空字符串，然后转换为SimpleGrantedAuthority
                authorities = permissions.stream()
                        .filter(permission -> permission != null && !permission.trim().isEmpty())
                        .map(SimpleGrantedAuthority::new)
                        .collect(Collectors.toList());
            }
            // 创建Authentication对象并设置到SecurityContext中
            UsernamePasswordAuthenticationToken authentication =
                    new UsernamePasswordAuthenticationToken(claims.getSubject(), null, authorities);
            SecurityContextHolder.getContext().setAuthentication(authentication);
        } catch (Exception e) {
            log.error("解析token失败: " + e.getMessage());
            // 只对需要认证的路径返回401错误
            SecurityContextHolder.clearContext();
            response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
            response.getWriter().write("{\"code\":403,\"message\":\"NOT LOGIN\"}");
            return;
        }
        filterChain.doFilter(request, response);
    }

    /**
     * 判断是否为公开路径
     */
    private boolean isPublicPath(String requestURI) {
        return "/login".equals(requestURI) ||
                requestURI.startsWith("/doc.html") ||
                requestURI.startsWith("/webjars") ||
                requestURI.startsWith("/v3/api-docs");
    }
}
